home *** CD-ROM | disk | FTP | other *** search
- #include "PICSDialogs.h"
- #include "PICSPreferencesDialog.h"
- #include "PICSCompositeDialog.h"
-
- #include "PICS_Composite.h"
- #include "PICS_Operations.h"
- #include "PICS_Types.h"
- #include "PICS_Info.h"
- #include "PICS_Utils.h"
-
- #include "Class_ProgressWindow.h"
- #include "FileRegistry.h"
- #include "CropPICTs.h"
- #include "StringUtils.h"
- #include "SavePicture.h"
-
- #include "SimpleError.h"
- #include "assert_mac.h"
-
- #include "main.h" // For AppEmergencyUpdate()
-
- #include "Monitors.h" // For GetDeepestDevice(), etc.
- #include "QDUtils.h" // For Set/HasMonitorDepth
- #include <QDOffscreen.h>
-
- // ---------------------------------------------------------------------------
-
- /*
- This does the *actual* compositing.
-
- This is a real complicated bastard! Due to the fact that we
- can crop or not crop, and assemble or not assemble, or a combo
- of the previous. Also, the output format is different depending
- on whether we assemble or not. If we do, the result is a composited
- PICT file; if not then we're just cropping and the result is
- a PICS file.
- Add the fact that the input PICS format is complicated by the
- usage of delta pictures! Makes me wanna cry...
- */
-
- void CompositePICS(
- CompositeOptions *options,
- FSSpec *picsFile,
- short fileRefNum,
- const Rect *areaToCrop) {
-
- Boolean openedResFile = false;
- short oldRefNum;
-
- ASSERT(options != NULL);
- ASSERT(areaToCrop != NULL);
-
- AppEmergencyUpdate();
-
- oldRefNum = CurResFile();
- if (picsFile != NULL && fileRefNum == -1) {
- fileRefNum = FSpOpenResFile(picsFile, fsRdWrPerm);
- if (!RegisterFile(fileRefNum)) {
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kCantOpenFileErrMsg);
- return;
- }
- openedResFile = true;
- }
-
- if (fileRefNum == -1) {
- SimpleError(kAlertErrID, kErrMsgID, kCantOpenFileErrMsg);
- return;
- }
-
- ProgressWindowPtr progressWindow;
- GraphicsBufferPtr inputPictBuffer;
- GraphicsBufferPtr outputCropBuffer;
- Rect inputPictBounds;
- Rect outputCropBounds;
- Rect cropRect;
- PicHandle inputPict;
- GDHandle outputDevice;
- GWorldPtr saveWorld;
- GDHandle saveDev;
- GBErr err;
- short origDepth;
- short numFrames;
- short offsetH, offsetV;
- PicHandle *outputPicts;
- long picSize, largestPicSize;
- PICSInfoRsrcHdl picsInfo;
- short picDepth;
-
- SetCursor(*GetCursor(watchCursor));
- UseResFile(fileRefNum);
-
- cropRect = *areaToCrop;
-
- numFrames = Count1Resources(kPICSRsrcType);
- if (numFrames < 1) {
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kNoPICTsInFileErrMsg);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
-
- if (options->frameStart == 0) {
- options->frameStart = 1; // Now set it to a valid index range
- options->frameStop = numFrames;
- }
-
- outputDevice = GetDeepestDevice();
- origDepth = GetDeviceDepth(outputDevice);
- progressWindow = new ProgressWindow(outputDevice,
- (options->frameStop - options->frameStart + 1) + options->frameStart + 2);
- SetPort(progressWindow->GetWindow());
- TextFont(geneva);
- TextSize(9);
- TextFace(bold);
-
- inputPict = (PicHandle)Get1Resource(kPICSRsrcType, kPICSRsrcStartID);
- if (inputPict == NULL) {
- // No 'PICT's with an id of 128. Probably not a PICS file.
- delete progressWindow;
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kInvalidPICSFormatErrMsg);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
- picDepth = GetPictDepth(inputPict);
- if (options->outputDepthType == kUsePICSFileOutputDepth) {
- options->outputDepth = picDepth;
- }
- inputPictBounds = (**inputPict).picFrame;
- offsetH = inputPictBounds.left;
- offsetV = inputPictBounds.top;
-
- picsInfo = GetPICSInfo();
- if (picsInfo != NULL)
- DetachResource((Handle)picsInfo);
-
- GetGWorld(&saveWorld, &saveDev);
- progressWindow->SetPrimaryMessage("\pSetting up input buffer...");
- progressWindow->Increment();
- if (options->outputDepth == 0) {
- CenterRect(&inputPictBounds, &(**outputDevice).gdRect);
- err = NewGraphicsBuffer(&inputPictBuffer, 0,
- (CP_Rect*)&inputPictBounds, kGBOptimalFlag, 0);
- }
- else {
- FlushRectTopLeft(&inputPictBounds);
- err = NewGraphicsBuffer(&inputPictBuffer, options->outputDepth,
- (CP_Rect*)&inputPictBounds, kGBOptimalFlag, 0);
- }
- if (err != noErr) {
- delete progressWindow;
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kNoGWorldErrMsg);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
- FlushRectTopLeft(&inputPictBounds);
-
- if (!options->doCrop) {
- cropRect = inputPictBounds;
- FlushRectTopLeft(&cropRect);
- }
-
- if (options->doAssemble) {
- progressWindow->SetPrimaryMessage("\pSetting up output buffer....");
- progressWindow->Increment();
-
- outputCropBounds = cropRect;
- FlushRectTopLeft(&outputCropBounds);
-
- if (options->assembleLeftToRight) {
- outputCropBounds.right = outputCropBounds.right *
- (options->frameStop - options->frameStart + 1);
- }
- else {
- outputCropBounds.bottom = outputCropBounds.bottom *
- (options->frameStop - options->frameStart + 1);
- }
-
- if (options->outputDepth == 0) {
- CenterRect(&outputCropBounds, &(**outputDevice).gdRect);
- err = NewGraphicsBuffer(&outputCropBuffer, 0,
- (CP_Rect*)&outputCropBounds, kGBOptimalFlag, 0);
- }
- else {
- FlushRectTopLeft(&outputCropBounds);
- err = NewGraphicsBuffer(&outputCropBuffer, options->outputDepth,
- (CP_Rect*)&outputCropBounds, kGBOptimalFlag, 0);
- }
- if (err != noErr) {
- delete progressWindow;
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kNoGWorldErrMsg);
- DisposeGraphicsBuffer(inputPictBuffer);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
- FlushRectTopLeft(&outputCropBounds);
- }
- else {
- outputPicts = (PicHandle*)NewPtr(sizeof(PicHandle) *
- (options->frameStop - options->frameStart + 1));
- outputCropBuffer = NULL;
- }
-
- Rect srcCropRect, destCropRect;
- Rect drawToRect, picFrame;
-
- srcCropRect = cropRect;
- destCropRect = srcCropRect;
- FlushRectTopLeft(&destCropRect);
-
- /*
- Because of the possibility of delta pictures, regardless
- of the frameStart parameter we have to
- go through and draw each picture in the PICS starting at
- the first one, id 128.
- */
- picSize = largestPicSize = 0;
- short resID;
- short frameCount = 0; // 1 to number of frames we're working on
- short endResID;
- Str15 frameCountStr;
-
- // We need to calculate the last resource id we'll be using:
- // The frame range starting resource id + the number of frames
- // (NOT the starting resource id of 128, unless frameStart is 1!)
- endResID = ((kPICSRsrcStartID + options->frameStart - 1)
- + (options->frameStop - options->frameStart + 1));
-
- progressWindow->SetPrimaryMessage("\pSetting up frame:");
-
- for (resID = kPICSRsrcStartID; resID < endResID; resID++) {
-
- SetGWorld(saveWorld, saveDev);
- if (resID == (kPICSRsrcStartID + options->frameStart - 1)) {
- progressWindow->SetPrimaryMessage("\pCompositing frame:");
- }
- NumToString(resID - kPICSRsrcStartID + 1, frameCountStr);
- progressWindow->SetSecondaryMessage(frameCountStr);
- progressWindow->Increment();
-
- /*
- First step: load in 'PICT' frame
- */
- inputPict = (PicHandle)Get1Resource(kPICSRsrcType, resID);
-
- if (inputPict == NULL) {
- delete progressWindow;
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kUnableLoadPICTErrMsg);
- DisposeGraphicsBuffer(inputPictBuffer);
- if (options->doAssemble)
- DisposeGraphicsBuffer(outputCropBuffer);
- else
- DisposePtr((Ptr)outputPicts);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
-
- /*
- Second step: make sure we draw into inputPictBuffer
- correctly (this includes adapting to possible
- existence of delta pictures)
- */
- SetGraphicsBuffer(inputPictBuffer);
- drawToRect = inputPictBounds;
-
- // Check for delta picture
- if (resID > kPICSRsrcStartID) {
- picFrame = (**inputPict).picFrame;
-
- // If first picture wasn't flushed topLeft (0,0), we
- // have to do the same compensation here
- OffsetRect(&picFrame, -offsetH, -offsetV);
-
- if (picFrame.left > drawToRect.left ||
- picFrame.top > drawToRect.top ||
- picFrame.right < drawToRect.right ||
- picFrame.bottom < drawToRect.bottom) {
- // Shucks! Delta pictures...
- drawToRect = picFrame;
- }
- }
- /*
- If it's a delta picture, we'll be drawing over the previous
- frame (the desired action). And if it's not a delta
- picture then this picture will completely overwrite the
- previous one. So in either case we don't have to worry about
- erasing the contents of <inputPictBuffer> before drawing.
- */
- DrawPicture(inputPict, &drawToRect);
-
- /*
- Third step: do we crop only or assemble (with or without
- cropping). We only do this if the picture is in the
- specified frame range...
- For assembling, determine compositing positions first.
- Then crop during the composition if cropping is desired.
- For cropping only, just capture the cropping process
- to a new picture.
- */
- if (resID >= (kPICSRsrcStartID + options->frameStart - 1)) {
-
- if (options->doAssemble) {
- // OK, now to do the actual cropping and compositing
- FlushRectTopLeft(&destCropRect);
- if (options->assembleLeftToRight)
- OffsetRect(&destCropRect, destCropRect.right * frameCount, 0);
- else
- OffsetRect(&destCropRect, 0, destCropRect.bottom * frameCount);
-
- // Do the crop now
- CopyGraphicsBuffer(inputPictBuffer, outputCropBuffer,
- (CP_Rect*)&srcCropRect, (CP_Rect*)&destCropRect);
-
- }
- else {
- FlushRectTopLeft(&destCropRect);
- if (!CapturePICT(inputPictBuffer, inputPictBuffer,
- &srcCropRect, &destCropRect, &outputPicts[frameCount])) {
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kUnexpectedErrMsg);
- ReleaseResource((Handle)inputPict);
- DisposeGraphicsBuffer(inputPictBuffer);
- DisposePtr((Ptr)outputPicts);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
- picSize = GetHandleSize((Handle)outputPicts[frameCount]);
- if (picSize > largestPicSize)
- largestPicSize = picSize;
- }
-
- frameCount++;
- }
-
- ReleaseResource((Handle)inputPict);
- }
-
- SetGWorld(saveWorld, saveDev);
- progressWindow->SetPrimaryMessage("\pDone.");
- progressWindow->FinishProgress();
- delete progressWindow;
-
- // So now we'll either have
- // a) array of Picture handles we'll have to save a PICT resources
- // b) one large composited graphicsBuffer we'll save as a PICT file
- if (options->doAssemble) {
- Str63 fileNameWithPrefix = kAssemblePrefix;
- PicHandle outputPict;
- WindowPtr previewWind;
-
- // Capture picture
- if (!CapturePICT(outputCropBuffer, outputCropBuffer,
- &outputCropBounds, &outputCropBounds, &outputPict)) {
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kUnexpectedErrMsg);
- DisposeGraphicsBuffer(inputPictBuffer);
- DisposeGraphicsBuffer(outputCropBuffer);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
-
- PrefsHandle prefs = LoadPrefs();
- if ((**prefs).compositePreview) {
- AppEmergencyUpdate();
-
- CenterRect(&outputCropBounds, &(**outputDevice).gdRect);
- previewWind = NewCWindow(NULL, &outputCropBounds, "\p ", false,
- plainDBox, (WindowPtr)-1, false, 0);
- FlushRectTopLeft(&outputCropBounds);
- ASSERT(previewWind != NULL);
-
- ShowWindow(previewWind);
- SetPort(previewWind);
- CopyGraphicsBuffer2Window(outputCropBuffer, previewWind,
- (CP_Rect*)&outputCropBounds, (CP_Rect*)&outputCropBounds);
-
- SetCursor(&qd.arrow);
- EventRecord theEvent;
- do {
- if (WaitNextEvent(everyEvent, &theEvent, 10, NULL)) {
- if (theEvent.what == mouseDown ||
- theEvent.what == keyDown)
- break;
- }
- } while(true);
- FlushEvents(everyEvent, 0);
- HideWindow(previewWind);
- DisposeWindow(previewWind);
- AppEmergencyUpdate();
- }
- OSType pictCreatorType = (**prefs).pictCreatorType;
- ReleaseResource((Handle)prefs);
-
- if (picsFile == NULL)
- PStrCat("\pComposited PICT", fileNameWithPrefix);
- else {
- PStrCat(picsFile->name, fileNameWithPrefix);
- PStrReplaceSuffix(kPICSSuffix, kPICTSuffix, fileNameWithPrefix);
- }
- if (fileNameWithPrefix[0] > 31)
- fileNameWithPrefix[0] = 31;
- SavePicture((Handle)outputPict, pictCreatorType, fileNameWithPrefix);
-
- KillPicture(outputPict);
- DisposeGraphicsBuffer(outputCropBuffer);
- }
- else {
- // Setup output PICS file
- short outputFileRef;
- StandardFileReply reply;
- OSErr myErr;
- Str63 fileNameWithPrefix = kCropPrefix;
-
- if (picsFile == NULL)
- PStrCat("\pComposited PICS", fileNameWithPrefix);
- else {
- PStrCat(picsFile->name, fileNameWithPrefix);
- }
- if (fileNameWithPrefix[0] > 31)
- fileNameWithPrefix[0] = 31;
-
- SetCursor(&qd.arrow);
- StandardPutFile("\pSave cropped PICS file as:",
- fileNameWithPrefix, &reply);
-
- AppEmergencyUpdate();
-
- if (reply.sfGood) {
- SetCursor(*GetCursor(watchCursor));
-
- // Determine creator type first.
- OSType creatorTypePICS;
- PrefsHandle prefs = LoadPrefs();
- if ((**prefs).changeCreator) {
- // Change it to become one of our files...
- creatorTypePICS = kPICSiliciousCreatorType;
- }
- else {
- // Keep it's original creator type
- FInfo fileInfo;
- myErr = FSpGetFInfo(&reply.sfFile, &fileInfo);
- if (myErr == noErr) {
- creatorTypePICS = fileInfo.fdCreator;
- }
- else {
- creatorTypePICS = kPICSiliciousCreatorType;
- }
- }
- ReleaseResource((Handle)prefs);
-
- // Replace first if necessary
- if (reply.sfReplacing) {
- myErr = FSpDelete(&reply.sfFile);
- if (myErr != noErr) {
- }
- }
-
- FSpCreateResFile(&reply.sfFile, creatorTypePICS,
- kPICSFileType1, reply.sfScript);
- myErr = ResError();
- if (myErr != noErr) {
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kCantCreateFileErrMsg);
- DisposeGraphicsBuffer(inputPictBuffer);
- DisposePtr((Ptr)outputPicts);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
-
- outputFileRef = FSpOpenResFile(&reply.sfFile, fsRdWrPerm);
- if (outputFileRef == -1 || !RegisterFile(outputFileRef)) {
- UseResFile(oldRefNum);
- SimpleError(kAlertErrID, kErrMsgID, kCantOpenFileErrMsg);
- DisposeGraphicsBuffer(inputPictBuffer);
- DisposePtr((Ptr)outputPicts);
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
- return;
- }
-
- progressWindow = new ProgressWindow(outputDevice,
- (options->frameStop - options->frameStart + 1));
- SetPort(progressWindow->GetWindow());
- TextFont(geneva);
- TextSize(9);
- TextFace(bold);
- progressWindow->SetPrimaryMessage("\pSaving frame:");
-
- UseResFile(outputFileRef);
- for (frameCount = 0, resID = kPICSRsrcStartID;
- frameCount < (options->frameStop - options->frameStart + 1);
- frameCount++, resID++) {
-
- NumToString(options->frameStart+frameCount, frameCountStr);
- progressWindow->SetSecondaryMessage(frameCountStr);
- progressWindow->Increment();
-
- if (!SavePictureResource(outputPicts[frameCount], outputFileRef, resID, NULL)) {
- }
- KillPicture(outputPicts[frameCount]);
- }
- progressWindow->SetPrimaryMessage("\pDone.");
- progressWindow->FinishProgress();
- delete progressWindow;
-
- // --------------------------
- // SAVE PICS INFO
- // --------------------------
- if (picsInfo == NULL) {
- // Create new 'INFO'
- picsInfo = NewPICSInfoResource();
- (**picsInfo).speed = kDefaultPICSSpeed;
- (**picsInfo).creatorType = kPICSiliciousCreatorType;
- }
- else {
- // Add detached 'INFO' from input file
- // to output file (& make it a resource)
- SavePICSInfo(picsInfo, false);
- }
- (**picsInfo).largestFrameSize = largestPicSize;
- if (options->outputDepth == 0 || options->outputDepth > 32)
- (**picsInfo).depth = picDepth;
- else
- (**picsInfo).depth = options->outputDepth;
- if (!SavePICSInfo(picsInfo, true)) {
- // ERROR HANDLING
- }
- DisposePICSInfo(picsInfo);
-
- (void)UnregisterFile(outputFileRef);
- CloseResFile(outputFileRef);
- }
- DisposePtr((Ptr)outputPicts);
- }
-
- DisposeGraphicsBuffer(inputPictBuffer);
-
- // Close file only if we had opened it ourself
- if (openedResFile) {
- (void)UnregisterFile(fileRefNum);
- CloseResFile(fileRefNum);
- }
-
- UseResFile(oldRefNum);
- SetCursor(&qd.arrow);
- } // END CompositePICS